#!/usr/bin/perl -w
#
#NOTES:
#
# use \savebox to make numbers align??
# use fractions for all computations
# add Nine Chapters problems w/ drop down menu

#
#PERL MODULES
#

use strict;
use CGI qw/:standard/;

#use CGI qw/-no_undef_params -nosticky :all/;
use CGI::Carp qw(fatalsToBrowser);

#
#VARIABLES
#

my $matrixNum;	# number index for preset matrices
my $nCols;		# number of columns, always 1 more than rows
my $nRows;		#appears to be number of rows in a matrix; $N = $#{ $matrixBook[$t][0] };
my $cintegers = 1;
my $cmatrix   = "";
my $denominator;
my $error = "";
my $formattedtabledata;
my $inputerror = "";
my $matrix     = "";
my $noninteger = 0;
my $pm         = "";
my $pm1        = 1;
my $print_a    = "";
my $query      = new CGI;
my $reducetens = 1;
my $step;    				#step
my $stepUser;				# step chosen by user through form
my $t            = 0;
my $table_a      = "";
my $table_header = "";
my $usegcf       = 0;
my @JZSSproblems = "";

#Matrices
my @matrixCalc;    			#a[$step][$i][$j]  ## Main Matrix (foundation) s=stage/step; (except this seems backwards)
my @a_tex = "";		# a, LaTeX
my @matrixCRod;				# Chinese counting rod matrices
my @xyc;			# counting rods, in xymatrix
my @c_tex = "";		# Chinese counting rod matrices, LaTeX
my @f_tex = "";		# formulas, LaTeX
my @matrixBook;				# matrices from books
my @u;				# user input from webpage

#Notes
my @boardnotes = "";
my @calcnotes  = "";
my @cresult    = "";
my @denom;
my @formula      = "";
my @formulanotes = "";
my @frac;
my @num;
my @output;
my @result = "";
my @sign;
my @xymatrix = "";

#
#MATRICES - Database of the problems; hash of hashes?
#

#JZSS
#3
$matrixBook[1] =
  [ [ "2", "1", "0", "1" ], [ "0", "3", "1", "1" ], [ "1", "0", "4", "1" ] ];

#12
$matrixBook[2] =
  [ [ "1", "1", "0", "40" ], [ "0", "2", "1", "40" ], [ "1", "0", "3", "40" ] ];

#13
$matrixBook[3] = [
	[ "2", "1", "0", "0", "0", "721" ],
	[ "0", "3", "1", "0", "0", "721" ],
	[ "0", "0", "4", "1", "0", "721" ],
	[ "0", "0", "0", "5", "1", "721" ],
	[ "1", "0", "0", "0", "6", "721" ]
];

#15
$matrixBook[4] =
  [ [ "2", "-1", "0", "1" ], [ "0", "3", "-1", "1" ], [ "-1", "0", "4", "1" ] ];

# YHJZSS
$matrixBook[5] = [
	[ "2", "1", "0", "2500" ],
	[ "0", "3", "1", "2500" ],
	[ "1", "0", "4", "2500" ]
];

#SXZJ
$matrixBook[6] = [
	[ "15", "1670", "0",   "0",     "106000" ],
	[ "0",  "800",  "264", "0",     "106000" ],
	[ "0",  "0",    "40",  "200",   "106000" ],
	[ "52", "0",    "0",   "175/3", "106000" ]
];

#744.4
$matrixBook[7] =
  [ [ "2", "1", "0", "1" ], [ "0", "3", "1", "1" ], [ "1", "0", "4", "2" ] ];

#747.3
$matrixBook[8] = [
	[ "4",  "-1", "0",  "300" ],
	[ "0",  "5",  "-1", "300" ],
	[ "-1", "0",  "6",  "300" ]
];

#750.2
$matrixBook[9] = [
	[ "2", "4", "0", "0", "40" ],
	[ "0", "2", "7", "0", "40" ],
	[ "0", "0", "4", "7", "30" ],
	[ "1", "0", "0", "8", "24" ]
];

#SFTZ
#4**
$matrixBook[10] =
  [ [ "1", "1", "0", "42" ], [ "0", "2", "1", "42" ], [ "1", "0", "3", "42" ] ];

#5**
$matrixBook[11] = [
	[ "2", "3", "0", "2040" ],
	[ "0", "5", "6", "640" ],
	[ "3", "0", "7", "2980" ]
];

#8**
$matrixBook[12] = [
	[ "2", "4", "0", "0", "40" ],
	[ "0", "2", "7", "0", "40" ],
	[ "0", "0", "4", "7", "30" ],
	[ "1", "0", "0", "8", "24" ]
];

#359.3
$matrixBook[13] = [
	[ "10", "1",  "0",  "0",  "1" ],
	[ "0",  "10", "2",  "0",  "1" ],
	[ "0",  "0",  "10", "3",  "1" ],
	[ "4",  "0",  "0",  "10", "1" ]
];

#366.4
$matrixBook[14] =
  [ [ "1", "1", "0", "42" ], [ "0", "2", "1", "42" ], [ "1", "0", "3", "42" ] ];

#372.3
$matrixBook[15] = [
	[ "2", "4", "0", "0", "40" ],
	[ "0", "2", "7", "0", "40" ],
	[ "0", "0", "4", "7", "30" ],
	[ "1", "0", "0", "8", "24" ]
];

#373.3
$matrixBook[16] = [
	[ "1", "8", "0", "0", "24" ],
	[ "0", "7", "4", "0", "30" ],
	[ "0", "0", "7", "2", "40" ],
	[ "2", "0", "0", "4", "40" ]
];

#374.1
$matrixBook[17] = [
	[ "2", "7", "0", "0", "40" ],
	[ "0", "4", "7", "0", "30" ],
	[ "0", "0", "8", "1", "24" ],
	[ "4", "0", "0", "2", "40" ]
];

$matrixBook[18] = [
	[ "1",   "1/3", "0",   "0",   "0",   "1442" ],
	[ "0",   "1",   "1/4", "0",   "0",   "1442" ],
	[ "0",   "0",   "1",   "1/5", "0",   "1442" ],
	[ "0",   "0",   "0",   "1",   "1/6", "1442" ],
	[ "1/2", "0",   "0",   "0",   "1",   "1442" ]
];

$matrixBook[19] = [
	[ "1",    "-1/3", "0",    "0",    "0",    "719" ],
	[ "0",    "1",    "-1/4", "0",    "0",    "719" ],
	[ "0",    "0",    "1",    "-1/5", "0",    "719" ],
	[ "0",    "0",    "0",    "1",    "-1/6", "719" ],
	[ "-1/2", "0",    "0",    "0",    "1",    "719" ]
];

$matrixBook[20] = [
	[ "1",   "-1/3", "0",    "0",    "0",    "0" ],
	[ "0",   "1",    "-1/4", "0",    "0",    "0" ],
	[ "0",   "0",    "1",    "-1/5", "0",    "0" ],
	[ "0",   "0",    "0",    "1",    "-1/6", "0" ],
	[ "1/2", "0",    "0",    "0",    "1",    "721" ]
];

$matrixBook[21] = [
	[ "10", "1",  "0",  "0",  "9976" ],
	[ "0",  "10", "2",  "0",  "9976" ],
	[ "0",  "0",  "10", "3",  "9976" ],
	[ "4",  "0",  "0",  "10", "9976" ]
];

$matrixBook[22] = [
	[ "2/5", "1",   "0",   "6780" ],
	[ "0",   "2/3", "1",   "6780" ],
	[ "1",   "0",   "2/7", "6780" ]
];

$matrixBook[23] = [
	[ "3", "30", "0",    "0",   "0",  "0",  "0",  "0",   "0",   "45" ],
	[ "0", "30", "-120", "0",   "0",  "0",  "0",  "0",   "0",   "0" ],
	[ "0", "0",  "100",  "-50", "0",  "0",  "0",  "0",   "0",   "0" ],
	[ "0", "0",  "0",    "30",  "30", "0",  "0",  "0",   "0",   "18" ],
	[ "0", "0",  "0",    "0",   "50", "10", "0",  "0",   "0",   "45" ],
	[ "0", "0",  "0",    "0",   "0",  "15", "17", "0",   "0",   "111/2" ],
	[ "0", "0",  "0",    "0",   "0",  "0",  "20", "-40", "0",   "28" ],
	[ "0", "0",  "0",    "0",   "0",  "0",  "0",  "20",  "-10", "0" ],
	[ "2", "0",  "0",    "0",   "0",  "0",  "0",  "0",   "80",  "34" ]
];

@JZSSproblems = ( 1 .. 23 );

#
# INITIALIZATION
#
#$step=0 unless $step= $query->param('s');

#
#  SUBROUTINES
#

#LOAD MATRIX SUBROUTINES

# comment has the better name
# Stage 0:
# info from database or from CGI module
# convert it into a matrix that we can operate on
# must be all integers
# converts fractions into integers by finding greatest common factor
sub elimfracs {    #subConvertFractionsToIntegers
	my ($step) = @_;
	foreach my $row ( 1 .. $nRows ) {
		foreach my $col ( 1 .. $nCols ) {
			if ( $matrixCalc[$row][$col][$step] =~ m/(\d+)\/(\d+)/ ) {
				my $num   = $1;
				my $denom = $2;
				my $gcf   = gcf( $num, $denom );
				$num   /= $gcf;
				$denom /= $gcf;
				foreach my $p ( 1 .. $nCols ) {
					$matrixCalc[$row][$p][$step] *= $denom;
				}
			}
		}
	}
	return @matrixCalc;
}

# puts matrix @matrixBook into matrix @matrixCalc
# iterates through all rows and columns to copy matrixM into matrixA
# trying to put matrix M into matrix a[0] (step 0)
# initializes A, step 0
# goes through and gets rid of all fractions as it copies
sub copy {    #not quite sure anymore what this does
	my ($t) = @_;	# passing in matrixNum
	$nRows = $#{ $matrixBook[$t][0] };
	$nCols = $nRows + 1;
	foreach my $row ( 1 .. $nRows ) {
		foreach my $col ( 1 .. $nCols ) {
			$u[$row][$col] =
			  $matrixBook[$t][ $row - 1 ][ $col - 1 ];      # @u is user inputted matrix
			if ( $matrixBook[$t][ $row - 1 ][ $col - 1 ] =~ s/^-// )
			{      # matching strings to find if plus or minus number
				$sign[$row][$col] = -1;  # problem converting strings into integers?
			}
			else {
				$sign[$row][$col] = 1;
			}
			if (   ( $matrixBook[$t][ $row - 1 ][ $col - 1 ] == "" )
				or ( $matrixBook[$t][ $row - 1 ][ $col - 1 ] =~ m/^0+$/ ) )
			{                        #blank or all zeros, possibly -
				$num[$row][$col]   = 0;
				$denom[$row][$col] = 1;
				$sign[$row][$col]  = 1;
			}
			elsif ( $matrixBook[$t][ $row - 1 ][ $col - 1 ] =~ m/^(\d+)$/ ) {
				$num[$row][$col]   = $1;
				$denom[$row][$col] = 1;
			}
			elsif ( $matrixBook[$t][ $row - 1 ][ $col - 1 ] =~ m/^(\d+)\/(\d+)$/ ) {
				$num[$row][$col]   = $1;
				$denom[$row][$col] = $2;
				if ( $denom[$row][$col] == 0 ) {
					$denom[$row][$col] = 1;    #print error??
				}
				my $gcf = gcf( $num[$row][$col], $denom[$row][$col] );
				$num[$row][$col]   /= $gcf || print "Divided by 0\n";
				$denom[$row][$col] /= $gcf || print "Divided by 0\n";
			}
			else {
				print "Error! \"$matrixBook[$t][$row - 1][$col - 1]\" \n";
			}
		}

		# if testing for fraction, setting denominator to 1, needs to be cut
		my $lcm = 1;
		my $gcf = gcf( $denom[$row][1], $denom[$row][2] );
		foreach my $col ( 3 .. $nCols ) {
			$gcf = gcf( $gcf, $denom[$row][$col] );
		}
		foreach my $col ( 1 .. $nCols ) {
			$lcm *= $denom[$row][$col];
			$lcm /= $gcf;
		}
		foreach my $col ( 1 .. $nCols ) {
			unless ( $denom[$row][$col] == 0 ) {
				$matrixCalc[$row][$col][$step] =
				  ( $sign[$row][$col] * $num[$row][$col] * $lcm ) / $denom[$row][$col];
			}
		}
	}
	return @matrixCalc;
}

# initializes A step 0 with random
sub randomMatrixCalc {    #subAssignRandomEntriesToMatrix
	my ($step) = @_;
	foreach my $row ( 1 .. $nRows ) {
		foreach my $col ( 1 .. $nRows ) {
			$matrixCalc[$row][$col][$step] = int( rand(8) ) + 1;
		}
		$matrixCalc[$row][ $nRows + 1 ][$step] = int( rand(149) ) + 1;
	}
	return @matrixCalc;
}

# takes old a, iterates to next step, copies to next step
sub next {
	my ($step) = @_;
	foreach my $i ( 1 .. $nRows ) {
		foreach my $j ( 1 .. $nCols ) {
			$matrixCalc[$i][$j][$step] =
			  $matrixCalc[$i][$j][ $step - 1 ];    # indices appear to be backwards
		}
	}
	return @matrixCalc;
}

# MATRIX CALCULATION SUBROUTINES
# vestigial tests for integers, not needed, not right
# no fractions involved, keep test just to avoid problems?
sub noninteger {                       #subMatrixHasNonIntegerEntry
	my ($step) = @_;
	$noninteger = 0;
	foreach my $row ( 1 .. $nRows ) {
		foreach my $col ( 1 .. $nCols ) {
			if ( $matrixCalc[$row][$col][$step] != int( $matrixCalc[$row][$col][$step] ) ) { $noninteger = 1 }
		}
	}
	return $noninteger;
}

# for the determinant; some will have alternating signs
# look at LaTeX output; is just creating for LaTeX
sub pm {    #subReturnPlusSignIfEvenMinusSignIfOdd
	my ($row) = @_;
	if ( $row % 2 == 0 ) { $pm = "+" }
	else { $pm = "-" }
	return $pm;
}

# gives the +/- for the actual calculations; cf. pm()
sub pm1 {    #subReturnOneIfEvenNegativeOneIfOdd
	my ($row) = @_;
	if ( $row % 2 == 0 ) { $pm1 = 1 }
	else { $pm1 = -1 }
	return $pm1;
}

sub determinants {

	#First part of calculation
	my $step = 0;    #steps for first part
	              # formats for display, before calculations
	elimfracs();
	$a_tex[$step] = a2tex();
	a2c($step);
	$c_tex[$step] = c2tex($step);

	$xymatrix[$step] = xysetneg($step);
	f2tex($step);
	$boardnotes[$step] .=
qq{<p>We arrange the entries on the counting board as follows (note that we remove any fractions by multiplying the entire column by a suitable integer):</p>};
	$calcnotes[$step] .=
	  qq{<p>This corresponds to the following augmented matrix:</p>};
	$formulanotes[$step] .=
qq{<p>Using variables, we can show what this corresponds to in terms of an exemplar:</p>};
	my $anN = $matrixCalc[$nRows][1][$step];

	foreach $step ( 1 .. $nRows - 2 ) {
		&next($step);
		$anN *= $matrixCalc[$step][ $step + 1 ][$step];
		$matrixCalc[$nRows][ $step + 1 ][$step] = pm1($step) * $anN;
		$a_tex[$step] = a2tex($step);
		a2c($step);
		$c_tex[$step]    = c2tex($step);
		$xymatrix[$step] = xysetneg($step);
		f2tex($step);
		my $x = $step + 1;
		my $y = $nRows - $step + 1;

#<img src="http://uts.cc.utexas.edu/~rhart/cgi-bin/mathtex.cgi?\\usepackage{euler}$matrixCalc[$nRows][$step][$step]" alt="" border=0 align=middle>
		$boardnotes[$step] .=
qq{<p>We multiply the entry located in <i>row $step column 1</i>,  namely <b>$matrixCalc[$nRows][$step][$step]</b>, by the entry in <i>row $x column $y</i>, which is <b>$matrixCalc[$step][$step+1][$step]</b>, change the sign, and place the result, <b>$matrixCalc[$nRows][$step+1][$step]</b>, in the entry located in <i>row $x column 1</i>:</p>};
		$calcnotes[$step] .=
		  qq{<p>This corresponds to the following augmented matrix:</p>};
		$formulanotes[$step] .=
qq{<p>Using variables, we can show what this corresponds to in terms of an exemplar:</p>};
	}

	#Second part of calculation
	# move in, 1 by 1, cross-multiply
	$step = $nRows - 1;
	&next($step);
	my $t = 1;    #steps for second part
	$formula[$step] = qq{ k_1 b_{$nRows} - l_{$nRows}b_1 };
	$result[$step] = $matrixCalc[1][1][$step] * $matrixCalc[$nRows][$nCols][$step] - $matrixCalc[$nRows][1][$step] * $matrixCalc[1][$nCols][$step];
	$matrixCalc[$nRows][$nCols][$step] = $result[$step];
	$cresult[$step]   = num2rods( $result[$step] );
	$xymatrix[$step]  = xycrossmult($step);
	my $tempa = $matrixCalc[1][1][ $step - 1 ] * $matrixCalc[$nRows][$nCols][ $step - 1 ];
	my $tempb = $matrixCalc[$nRows][1][ $step - 1 ] * $matrixCalc[1][$nCols][ $step - 1 ];
	$boardnotes[$step] .= qq{<p>We now begin a kind of "cross-multiplication": </p>
	<p>(1) We begin with the entry located in <i>row $nCols column 1</i>,  which at the beginning of this calculation, from the previous step, was originally <b>$matrixCalc[$nRows][$nCols][$step-1]</b>. </p>
	<p>(2) We then multiply this entry by the entry in <i>row 1 column $nRows</i>, which is <b>$matrixCalc[1][1][$step-1]</b>, giving <b> $matrixCalc[$nRows][$nCols][$step-1] * $matrixCalc[1][1][$step-1]</b>, and replace the entry in <i>row $nCols column 1</i> with this temporary result, <b>$tempa</b>. </p>
	<p>(3) We then multiply the entry in <i> row $nCols column $nRows</i>, <b> $matrixCalc[1][$nCols][$step-1]</b>, by the entry in <i> row 1 column 1</i>, <b> $matrixCalc[$nRows][1][$step-1]</b>, giving <b> $matrixCalc[1][$nCols][$step-1] * $matrixCalc[$nRows][1][$step-1]  = $tempb</b>.  </p>
	<p>(4) Finally, we subtract the result from the previous step, <b>$tempb</b>, from the temporary entry currently in <i>row $nCols column 1</i>,  <b> $tempa - $tempb </b>, and then again replace the entry in <i>row $nCols column 1</i> with the result, <b>$result[$step]</b>.</p>};

	foreach $t ( 2 .. $nRows - 1 ) {
		$step = $nRows + $t - 2;
		&next($step);

		#calculate result
		$result[$step] =
		  ( $result[ $step - 1 ] * $matrixCalc[$t][$t][$step] ) -
		  ( $matrixCalc[$nRows][$t][$step] * $matrixCalc[$t][$nCols][$step] );
		$matrixCalc[$nRows][$nCols][$step] = $result[$step];

		#convert to cresult
		$cresult[$step] = num2rods( $result[$step] );

		#create formula
		$formula[$step] = "(" . $formula[ $step - 1 ];
		pm($t);
		$formula[$step] .= qq{ ) k_{$t}  $pm };
		$formula[$step] .= qq{ l_{$nRows} };
		foreach my $i ( 1 .. $t - 1 ) {
			if ( $i < $t - 1 ) {
				$formula[$step] .= qq{ l_{$i}  };
			}
		}
		my $u = $t - 1;    # here a scalar, local variable; is a step
		$formula[$step] .= qq{ l_{$u} b_{$t} };
		$xymatrix[$step] = xycrossmult($step);
		my $x     = $t + 1;
		my $y     = $nRows - $t + 1;
		my $tempa = $result[ $step - 1 ] * $matrixCalc[$t][$t][$step];
		my $tempb = $matrixCalc[$nRows][$t][$step] * $matrixCalc[$t][$nCols][$step];
		$boardnotes[$step] .= qq{<p>We continue "cross-multiplication": </p>
	<p>(1) We again begin with the entry located in <i>row $nCols column 1</i>,  which at the beginning of this calculation, from the previous step, was originally <b>$result[$step-1]</b>. </p>
	<p>(2) We then multiply this entry by the entry in <i>row $t column $y</i>, which is <b>$matrixCalc[$t][$t][$step]</b>, giving <b> $result[$step-1] * $matrixCalc[$t][$t][$step]</b>, and replace the entry in <i>row $nCols column 1</i> with the temporary result <b>$tempa</b>. </p>
	<p>(3) We then multiply the entry in <i> row $nCols column $y</i>, <b>$matrixCalc[$t][$nCols][$step]</b> by the entry in <i> row 1 column $t</i>, <b>$matrixCalc[$nRows][$t][$step]</b>, giving <b>  $matrixCalc[$t][$nCols][$step] * $matrixCalc[$nRows][$t][$step] = $tempb</b>.  </p>
	<p>(4) Finally, we subtract the result from the previous step, <b>$tempb</b>, from the temporary entry currently in <i>row $nCols column 1</i>, <b> $tempa </b>, namely <b> $tempa - $tempb </b>, and then replace the temporary entry in <i>row $nCols column 1</i> with the result, <b>$result[$step]</b>.</p>
	<p>The resulting formula is shown below the diagram.</p>};
	}

	#Third part: calculate result
	# will probably have to be rewritten by Roger
	# counting board is blank, he now knows how to write it
	# NOTE: Doesn't appear to actually calculate anything, instead, is formatting for display
	$step++;
	$denominator = 1;
	foreach my $row ( 1 .. $nRows ) {
		$denominator *= $matrixCalc[$row][$row][0];
	}
	my $subtractand = -$matrixCalc[$nRows][1][0];
	foreach my $row ( 1 .. $nRows - 1 ) {
		$subtractand *= -$matrixCalc[$row][ $row + 1 ][0];
	}
	$denominator -= $subtractand;
	frac( 1, 0, $result[ $step - 1 ], $denominator );
	$result[$step] = "x_{$nRows} = ";
	if ( $frac[2] == 0 ) {
		$result[$step] .= $frac[0] * $frac[1];
	}
	else {
		if ( $frac[0] == 1 ) {
			$result[$step] .= "\\frac{$frac[2]}{$frac[3]}";
		}
		else {
			$result[$step] .= "-\\frac{$frac[2]}{$frac[3]}";
		}

#$result[$nRows] = " \\text{ or } $mixedfrac[0]\\frac{$mixedfrac[1]}{$mixedfrac[2]}"
	}

	#convert to cresult
	#$cresult[$row] = num2rods($result[$row]);
	#create formula
	my $denom = "";
	foreach my $row ( 1 .. $nRows ) {
		$denom .= "k_{$row}";
	}
	$denom .= "$pm";
	foreach my $row ( 1 .. $nRows ) {
		$denom .= "l_{$row}";
	}
	$formula[$step] = "x_{$nRows} = \\frac{" . $formula[ $step - 1 ] . "}{$denom}}";
	$boardnotes[$step] .= qq{<p>The final result: </p>};
}

sub gcf {
	my ( $x, $y ) = @_;
	( $x, $y ) = ( $y, $x % $y ) while $y;
	return $x;
}

# if everything a multiple of tens, they'd reduce
sub reducetens {
	my ($row) = @_;
	if ($reducetens) {
		my $alltens = 1;
		while ($alltens) {
			foreach my $col ( 0 .. $nCols ) {
				if ( int( $matrixCalc[$row][$col][$step] / 10 ) != ( $matrixCalc[$row][$col][$step] / 10 ) ) {
					$alltens = 0;
				}
			}
			if ($alltens) {
				foreach my $col ( 1 .. $nCols ) {
					$matrixCalc[$row][$col][$step] = $matrixCalc[$row][$col][$step] / 10;
				}
			}
		}
	}
}

# part of Gaussian elimination, not determinants
sub rowReduction {
	foreach my $i ( 1 .. ( $nRows - 1 ) ) {
		if ( $matrixCalc[$i][$i][$step] != 0 ) {    #need else: use another pivot
			foreach my $row ( ( $i + 1 ) .. $nRows ) {
				if ( $matrixCalc[$row][$i][$step] != 0 ) {
					if ( $matrixCalc[$i][$i][$step] == $matrixCalc[$row][$i][$step] ) {
						foreach my $col ( $i .. $nCols ) {
							$matrixCalc[$row][$col][$step] =
							  ( $matrixCalc[$row][$col][$step] - $matrixCalc[$i][$col][$step] );
						}
						reducetens($row);
					}
					else {
						my $gcf = 1;
						if ($usegcf) {
							$gcf = gcf( $matrixCalc[$i][$i][$step], $matrixCalc[$row][$i][$step] );
						}
						my $nmult = $matrixCalc[$i][$i][$step] / $gcf;
						my $imult = $matrixCalc[$row][$i][$step] / $gcf;
						foreach my $col ( 1 .. $nCols ) {
							$matrixCalc[$row][$col][$step] =
							  $nmult * $matrixCalc[$row][$col][$step] - $imult * $matrixCalc[$i][$col][$step];
						}
						reducetens($row);
					}
				}
			}
		}
		$a_tex[$i] = a2tex();
		noninteger;
		a2c();
		$c_tex[$i] = c2tex();
	}
}

# also part of Gaussian
sub backSubstitution {
	foreach my $i ( reverse( 1 .. ( $nRows - 1 ) ) ) {
		my $bi = 0;
		$bi += $matrixCalc[$nRows][$nRows][$step] * $matrixCalc[$i][$nCols][$step];
		foreach my $j ( reverse( ( $i + 1 ) .. $nRows ) ) {
			$bi -= $matrixCalc[$j][$nCols][$step] * $matrixCalc[$i][$j][$step];
		}
		if ( $matrixCalc[$i][$i][$step] == 0 ) {
			$error .= "ann = $matrixCalc[$i][$i][$step] for n = $i<p>";
		}
		else {
			$bi /= $matrixCalc[$i][$i][$step];
			if ( int($bi) != $bi ) {
				$error .= "bi = $bi for n = $i<p>";
			}
			$matrixCalc[$i][$nCols][$step] = $bi;
			foreach my $k ( reverse( $i .. $nRows ) ) {
				$matrixCalc[$i][$k][$step] = 0;
			}
		}
		noninteger();
		$a_tex[ 2 * $nRows - $i ] = a2tex();
		a2c();
		$c_tex[ 2 * $nRows - $i ] = c2tex();
	}
}

#Fraction subroutines - Can all disappear; no fractions used

sub add { }

sub subtract { }

sub multiply { }

sub divide { }

sub reduce { }

sub frac {
	my ( $sign, $int, $num, $denom ) = @_;

	#put sign in $sign
	if ( $int != abs($int) )     { $int   *= -1; $sign *= -1 }
	if ( $num != abs($num) )     { $num   *= -1; $sign *= -1 }
	if ( $denom != abs($denom) ) { $denom *= -1; $sign *= -1 }

	#calculate if fraction
	if ( $num != 0 ) {
		$num += $int * $denom;
		$int = 0;
		unless ( $denom == 0 ) {    #make sure not dividing by 0
			$int = int( $num / $denom );
			if ( $num / $denom == $int ) {    #if result is integer
				$num   = 0;
				$denom = 1;
			}
			else {
				my $gcf = gcf( $num, $denom );
				$num   /= $gcf;
				$denom /= $gcf;
			}
		}
	}
	@frac = ( $sign, $int, $num, $denom );
	return @frac;
}

#PRINT MATRIX SUBROUTINES
# makes them into counting rods; is for LaTeX
# not for calculations, is strictly output
# but may not be valid here anymore, moved to TeX macros
sub a2c {
	my ($step) = @_;
	unless ($noninteger) {
		foreach my $row ( 1 .. $nRows ) {
			foreach my $col ( 1 .. $nCols ) {
				$matrixCRod[$step][$row][$col] = num2rods( $matrixCalc[$row][$col][$step] );
			}
		}
	}
	return @matrixCRod;
}

# not being used anymore; now done through a TeX macro
sub num2rods {
	my ($number) = @_;

	# unless ($noninteger) {}
	my $rods = "";
	if ( $number >= 0 ) {
		while ( $number ne "" ) {
			my $digit = "";
			$number =~ s/\d$//;
			$digit = $&;
			$rods  = "~" . $rods unless ( $rods eq "" );
			$rods  = "\\zero" . $rods if $digit == 0;
			$rods  = "\\one" . $rods if $digit == 1;
			$rods  = "\\two" . $rods if $digit == 2;
			$rods  = "\\three" . $rods if $digit == 3;
			$rods  = "\\four" . $rods if $digit == 4;
			$rods  = "\\five" . $rods if $digit == 5;
			$rods  = "\\six" . $rods if $digit == 6;
			$rods  = "\\seven" . $rods if $digit == 7;
			$rods  = "\\eight" . $rods if $digit == 8;
			$rods  = "\\nine" . $rods if $digit == 9;
			if ( $number ne "" ) {
				my $ten = "";
				$number =~ s/\d$//;
				$ten  = $&;
				$rods = "~" . $rods;
				$rods = "\\zero" . $rods if $ten == 0;
				$rods = "\\ten" . $rods if $ten == 1;
				$rods = "\\twenty" . $rods if $ten == 2;
				$rods = "\\thirty" . $rods if $ten == 3;
				$rods = "\\forty" . $rods if $ten == 4;
				$rods = "\\fifty" . $rods if $ten == 5;
				$rods = "\\sixty" . $rods if $ten == 6;
				$rods = "\\seventy" . $rods if $ten == 7;
				$rods = "\\eighty" . $rods if $ten == 8;
				$rods = "\\ninety" . $rods if $ten == 9;
			}
		}
	}
	else {
		$number = -$number;
		while ( $number ne "" ) {
			my $digit = "";
			$number =~ s/\d$//;
			$digit = $&;
			$rods  = "~" . $rods unless ( $rods eq "" );
			$rods  = "\\Zero" . $rods if $digit == 0;
			$rods  = "\\One" . $rods if $digit == 1;
			$rods  = "\\Two" . $rods if $digit == 2;
			$rods  = "\\Three" . $rods if $digit == 3;
			$rods  = "\\Four" . $rods if $digit == 4;
			$rods  = "\\Five" . $rods if $digit == 5;
			$rods  = "\\Six" . $rods if $digit == 6;
			$rods  = "\\Seven" . $rods if $digit == 7;
			$rods  = "\\Eight" . $rods if $digit == 8;
			$rods  = "\\Nine" . $rods if $digit == 9;

			if ( $number ne "" ) {
				my $ten = "";
				$number =~ s/\d$//;
				$ten  = $&;
				$rods = "~" . $rods;
				$rods = "\\Zero" . $rods if $ten == 0;
				$rods = "\\Ten" . $rods if $ten == 1;
				$rods = "\\Twenty" . $rods if $ten == 2;
				$rods = "\\Thirty" . $rods if $ten == 3;
				$rods = "\\Forty" . $rods if $ten == 4;
				$rods = "\\Fifty" . $rods if $ten == 5;
				$rods = "\\Sixty" . $rods if $ten == 6;
				$rods = "\\Seventy" . $rods if $ten == 7;
				$rods = "\\Eighty" . $rods if $ten == 8;
				$rods = "\\Ninety" . $rods if $ten == 9;
			}
		}
	}
	return $rods;
}

# formulas to TeX
sub f2tex {
	my ($step) = @_;
	$f_tex[$step] = "";
	foreach my $row ( 1 .. $nRows ) {
		foreach my $col ( 1 .. $nRows ) {
			if ( $row == $nRows and $col == 1 ) {
				$f_tex[$step] .= qq{ l_{$nRows} & };
			}
			elsif ( $row == $nRows and $col <= $step + 1 ) {
				if ( $col % 2 == 0 ) {
					$f_tex[$step] .= qq{ - };
				}
				my $r = $col - 1;
				$f_tex[$step] .= qq{ l_{$nRows} };
				foreach my $i ( 1 .. $step - 1 ) {
					if ( $i < $col - 1 ) {
						$f_tex[$step] .= qq{ l_{$i}  };
					}
				}
				$f_tex[$step] .= qq{ l_{$r} & };
			}
			elsif ( $col == $row ) {
				$f_tex[$step] .= qq{ k_{$row} & };
			}
			elsif ( $col == $row + 1 ) {
				$f_tex[$step] .= qq{ l_{$row} & };
			}
			else {
				$f_tex[$step] .= qq{ 0 & };
			}
		}
		$f_tex[$step] .= qq{ b_{$row} \\\\  };
	}
	return $f_tex[$step];
}

# printing the tables that can take input through CGI
sub a2table {
	$print_a = qq{<table>};
	my $format = "";
	my $i      = 0;
	foreach my $row ( 1 .. $nRows ) {
		$print_a .= qq{<tr>};
		foreach my $col ( 1 .. $nRows ) {
			if ( ( $col == $row + 1 ) or ( $col == $row ) or ( $col == 1 and $row == $nRows ) )
			{
				$print_a .=
qq{<td><input type="text" name="u[$row][$col]" default value="$u[$row][$col]" align="center" size="5" maxlength="5" border="0"></td>};
			}
			else {
				$print_a .= qq{<td>0</td>};
			}
		}
		$print_a .=
qq{<td><input type="text" name="u[$row][$nCols]" default value="$u[$row][$nCols]" size="5" maxlength="5" border="0" align="center"></td>};
		$print_a .= qq{</tr>};
	}
	$print_a .= qq{</table>};
	return $print_a;
}

# outputs as augmented matrix with numbers
sub a2tex {
	my ($step) = @_;
	$matrix = "";
	foreach my $row ( 1 .. $nRows ) {
		foreach my $col ( 1 .. $nRows ) {
			$matrix .= qq|\\pn| unless $matrixCalc[$row][$col][$step] < 0;
			$matrix .= qq{ $matrixCalc[$row][$col][$step] & };
		}
		$matrix .= qq|\\pn| unless $matrixCalc[$row][$nCols][$step] < 0;
		$matrix .= qq{ $matrixCalc[$row][$nCols][$step] \\\\ };
	}
	return $matrix;
}

sub c2tex {
	my ($step) = @_;
	$cmatrix = "";
	unless ($noninteger) {
		foreach my $col ( 1 .. $nCols ) {
			foreach my $row ( reverse( 2 .. $nRows ) ) {
				$cmatrix .= qq{ $matrixCRod[$step][$row][$col] ~ \\vline ~ & };
			}
			$cmatrix .= qq{ $matrixCRod[$step][1][$col] \\\\  };
			unless ( $col == $nCols ) { $cmatrix .= qq{  \\hline   } }
		}
	}
	return $cmatrix;
}

# xymatrix subroutines
# ignore these; xy is a frustrating LaTeX macro language
# handles arrows, etc.
# needs to stay as is
# can consider improving the Perl code, but not the XY code

sub xycolwidth {
	my ($step) = @_;
	foreach my $i ( 1 .. $nRows ) {
		my $maxwidth = 0;
		foreach my $j ( 1 .. $nCols ) {
			my $width = ( $matrixCalc[$i][$j][$step] =~ s/\d/$&/g );
			if ( $width > $maxwidth ) { $maxwidth = $width }
		}
		my $size = 7 * $maxwidth;
		$size .= "mm";
		foreach my $j ( 1 .. $nCols ) {
			$xyc[$step][$i][$j][0] = $maxwidth;
		}
	}
	return @xyc;
}

sub addgrid {
	my ($step) = @_;
	foreach my $i ( reverse( 2 .. $nRows ) ) {
#		my $d .= "d" x ( $nCols - 1 );
		$xyc[$step][$i][1][2] .= qq|\\zud|;
	}
	foreach my $j ( 2 .. $nCols ) {
#		my $l .= "l" x ( $nRows - 1 );
		$xyc[$step][1][$j][2] .= qq|\\zlr|;
	}
}

sub xyentries2grid {
	my ($step) = @_;
	my $xyentries2grid = "";
	addgrid($step);
	foreach my $i ( reverse( 2 .. $nRows ) ) {
#		my $d .= "d" x ( $nCols - 1 );
		$xyentries2grid .=
qq|\\zq{$matrixCalc[$i][1][$step]}{$xyc[$step][$i][1][0]}{$xyc[$step][$i][1][1]}{$xyc[$step][$i][1][2]} &|;
	}
	$xyentries2grid .=
qq|\\zq{$matrixCalc[1][1][$step]}{$xyc[$step][1][1][0]}{$xyc[$step][1][1][1]}{$xyc[$step][1][1][2]}\\\\|
	  ;    #   \\ar\@<1ex>[$d]
	foreach my $j ( 2 .. $nCols ) {
		foreach my $i ( reverse( 2 .. $nRows ) ) {
			$xyentries2grid .=
qq|\\zq{$matrixCalc[$i][$j][$step]}{$xyc[$step][$i][$j][0]}{$xyc[$step][$i][$j][1]}{$xyc[$step][$i][$j][2]}&|;
		}
#		if ( $j == 1 ) {
#			$xyentries2grid .=
#qq|\\zq{$matrixCalc[1][$nCols][$step]}{$xyc[$step][1][$nCols][0]}{$xyc[$step][1][$nCols][1]}{$xyc[$step][1][$nCols][2]}\\\\|;
#		}
#		else {
#			my $l .= "l" x ( $nRows - 1 );
			$xyentries2grid .=
qq|\\zq{$matrixCalc[1][$j][$step]}{$xyc[$step][1][$j][0]}{$xyc[$step][1][$j][1]}{$xyc[$step][1][$j][2]}\\\\|;
#		}
	}
	return $xyentries2grid;
}

sub xysetneg
{ #NOTE: AVOID % in expressions for mathtex -- I don't know if lines are separated!
	my ($step) = @_;
	unless ($noninteger) {

		#First make all the entries in each column the same width
		#Second add boxes and arrows where appropriate
		if ( $step == 0 ) {
			xycolwidth($step);
			foreach my $i ( reverse( 1 .. $nRows ) ) {
				foreach my $j ( 1 .. $nCols ) {
					$xyc[$step][$i][$j][1] = qq|m|;
					$xyc[$step][$i][$j][2] = qq||;
				}
			}
		}
		elsif ( $step > 0 ) {

			#make boxes
			foreach my $i ( reverse( 1 .. $nRows ) ) {
				foreach my $j ( 1 .. $nCols ) {

					#$xyc[$step][$i][$j][2] .= qq| ($i,$j) |;
					#$xyc[$step][$i][$j][1] = qq|f|;
					if ( $j == ( $step + 1 ) and $i == $step ) {
						$xyc[$step][$i][$j][1] = qq|f|;    #   \\ar\@<1ex>[$d]
					}
					elsif ( $j == $step and $i == $nRows ) {
						$xyc[$step][$i][$j][1] = qq|f|;    #
					}
					elsif ( $j == ( $step + 1 ) and $i == $nRows ) {
						$xyc[$step][$i][$j][1] = qq|f|;    # *+<2mm,2mm>[F-:<4pt>]
					}
					else {
						$xyc[$step][$i][$j][1] = qq|m|;    #to keep sizes the same
					}
				}
			}

			#make columns equal
			xycolwidth($step);

			#add arrows
			foreach my $i ( reverse( 1 .. $nRows ) ) {
				foreach my $j ( 1 .. $nCols ) {

					#$xyc[$step][$i][$j][2] .= qq| ($i,$j) |;
					if ( $j == ( $step + 1 ) and $i == ($step) ) {
						my $u .= "u";
						my $d .= "d" x $nCols;
						my $l .= "l" x ( $nRows - $step );
						$xyc[$step][$i][$j][2] =
						  qq|\\POS[]+U\\ar\@/_5mm/[$u$l]|;   #   \\ar\@<1ex>[$d]
					}
					elsif ( $j == $step and $i == $nRows ) {
						$xyc[$step][$i][$j][2] = qq|\\POS[]+R\\ar\@/^5mm/[d]+R|;  #
					}
				}
			}
		}

		#Finally, place entries and add grid
		$xymatrix[$step] = xyentries2grid($step);
	}
	return $xymatrix[$step];
}

sub xycrossmult {    #NOTE: First place entries, then place arrows
	my ($step) = @_;
	my $t = $step - $nRows + 2;
	unless ($noninteger) {

		#Set the answer in aNM
		$matrixCRod[$step] = $matrixCRod[ $nRows - 2 ];
		$matrixCRod[$step][$nRows][$nCols] = $cresult[$step];

		#First add boxes where appropriate
		foreach my $i ( reverse( 1 .. $nRows ) ) {
			foreach my $j ( 1 .. $nCols ) {
				if ( $i == $nRows and $j == $nCols ) {    #add save/restores?
					$xyc[$step][$i][$j][1] = qq|f|;
				}
				elsif ( $i == $t and $j == $t ) {
					my $d .= "d" x ( $nRows - $t + 1 );
					my $l .= "l" x ( $nRows - $t );
					$xyc[$step][$i][$j][1] = qq|f|;
				}
				elsif ( $i == $t and $j == $nCols ) {
					my $d .= "d" x ( $nRows - $t + 1 );
					my $l .= "l" x ( $nRows - $t );
					$xyc[$step][$i][$j][1] .= qq|f|;
				}
				elsif ( $i == $nRows and $j == $t ) {
					my $d .= "d" x ( $nRows - $t + 1 );
					my $r .= "r" x ( $nRows - $t );
					$xyc[$step][$i][$j][1] .= qq|f|;
				}
				else {
					$xyc[$step][$i][$j][1] = qq|m|;    #to keep sizes the same
					  #$xyc[$step][$i][$j][2] = qq| { \\tiny{($i,$j)} $matrixCRod[$nRows-2][$i][$j]} |;
				}
			}
		}

		#Second make columns equal
		xycolwidth($step);

		#Third add arrows where appropriate
		my $curve;
		my $offset;
		my $r = $nRows - 2;
		foreach my $i ( reverse( 1 .. $nRows ) ) {
			foreach my $j ( 1 .. $nCols ) {
				if ( $i == $t and $j == $t ) {
					my $d .= "d" x ( $nRows - $t + 1 );
					my $l .= "l" x ( $nRows - $t );
					if ( $t <= $nRows - 2 ) { $curve = "8mm"; $offset = "+UR" }
					else { $curve = "2mm"; $offset = "+UR+<-2mm,0mm>" }
					$xyc[$step][$i][$j][2] .=
					  qq|\\POS[]+L+<2mm,0mm>\\ar\@/_$curve/[$l$d]$offset|;
				}
				elsif ( $i == $t and $j == $nCols ) {
					my $d .= "d" x ( $nRows - $t + 1 );
					my $l .= "l" x ( $nRows - $t );
					if ( $t <= $nRows - 2 ) { $curve = "8mm"; $offset = "" }
					else { $curve = "2mm"; $offset = "" }
					$xyc[$step][$i][$j][2] .=
					  qq|\\POS[]+L+<1mm,0mm>\\ar\@/^$curve/[$l]+R|;
				}
				elsif ( $i == $nRows and $j == $t ) {
					my $d .= "d" x ( $nRows - $t + 1 );
					my $r .= "r" x ( $nRows - $t );
					if ( $t <= $nRows - 2 ) { $curve = "4mm"; $offset = "+UL" }
					else { $curve = "1mm"; $offset = "+U" }
					$xyc[$step][$i][$j][2] .=
					  qq|\\POS[]+R\\ar\@/^$curve/[$d$r]$offset|;
				}
			}
		}

#$xyc[$step][$nRows][1][2] .= qq| t=$t; |;
#Finally, place entries and add grid
#$matrixCRod[$step][1][1] = qq| {\\setlength\\fboxrule{0pt}\\fbox{New $step Old cell $matrixCRod[$nRows-2][1][1]}} |;
		$xymatrix[$step] = xyentries2grid($step);
	}
	return $xymatrix[$step];
}

sub final
{ #NOTE: AVOID % in expressions for mathtex -- I don't know if lines are separated!
	my ($step) = @_;
	my $t = $step - $nRows + 2;
	unless ($noninteger) {

		#Set the answer in aNM
		$matrixCRod[$step] = $matrixCRod[ $nRows - 2 ];
		$matrixCRod[$step][$nRows][$nCols] = $cresult[$step];

		#First make all the entries in each column the same width
		xycolwidth($step);

		#Second add boxes and arrows where appropriate
		my $curve = "1mm";
		my $r     = $nRows - 2;
		if ( $t <= $nRows - 2 ) {
			$curve = "5mm";
		}
		foreach my $i ( reverse( 1 .. $nRows ) ) {
			foreach my $j ( 1 .. $nCols ) {
				if ( $i == $nRows and $j == $nCols ) {
					$xyc[$step][$i][$j][2] .= qq| \\fbox{$matrixCRod[$step][$i][$j] } |;
				}
				elsif ( $i == $t and $j == $t ) {
					my $d .= "d" x ( $nRows - $t + 1 );
					my $l .= "l" x ( $nRows - $t );
					$xyc[$step][$i][$j][2] .=
qq| \\fbox{$matrixCRod[$step][$i][$j] }\\POS[]+DL+<1mm,1mm> \\ar\@/_$curve/[$l$d]+UR+<-1mm,-1mm> |;
				}
				elsif ( $i == $t and $j == $nCols ) {
					my $d .= "d" x ( $nRows - $t + 1 );
					my $l .= "l" x ( $nRows - $t );
					$xyc[$step][$i][$j][2] .=
qq| \\fbox{$matrixCRod[$step][$i][$j]} \\POS[]+DL+<1mm,1mm> \\ar\@/^$curve/[$l]+DR+<-1mm,1mm>  |;
				}
				elsif ( $i == $nRows and $j == $t ) {
					my $d .= "d" x ( $nRows - $t + 1 );
					my $r .= "r" x ( $nRows - $t );
					$xyc[$step][$i][$j][2] .=
qq| \\fbox{$matrixCRod[$step][$i][$j]}\\POS[]+DR+<-1mm,1mm> \\ar\@/^$curve/[$d$r]+UL+<1mm,-1mm> |;
				}
				else {
					$xyc[$step][$i][$j][2] =
					  qq| {\\setlength\\fboxrule{0pt}\\fbox{$matrixCRod[$step][$i][$j]}} |;

			   #$xyc[$step][$i][$j][2] = qq| { \\tiny{($i,$j)} $matrixCRod[$nRows-2][$i][$j]} |;
				}
			}
		}

#$xyc[$step][$nRows][1][2] .= qq| t=$t; |;
#Finally, place entries and add grid
#$matrixCRod[$step][1][1] = qq| {\\setlength\\fboxrule{0pt}\\fbox{New $step Old cell $matrixCRod[$nRows-2][1][1]}} |;
		$xymatrix[$step] = xyentries2grid($step);
	}
	return $xymatrix[$step];
}

#PRINT HTML SUBROUTINES
# here's where he wants the most help
# improve the HTML

sub print_header
{ # style = "font-size: 12px; font-family: 'Impact'; background-color : yellow;  font-weight : bold;  font-size: 12px; font-family: 'Helvetica'; text-decoration : underline"
	my $print_header = qq{ 
		<style type="text/css">
		p {font-family: serif; font-weight: lighter;}
		h3 {font-family: Arial Arial Black; font-weight: bolder; }
		th {font-family: Arial Arial Black; font-size: small; text-align: center; vertical-align: bottom; border-collapse: collapse; border-spacing: 0px 0px;}
		td {font-family: Arial Arial Black; text-align: center; vertical-align: center; border-collapse: collapse; border-spacing: 0px 0px; width: 5em}
		table {border-collapse: separate; border-spacing: 0px 1px; border: 1px solid black; table-layout: fixed; font-color: blue; } 
		</style> };    # background-color: #bbf
	             # 	$print_header .= qq{<tr><th colspan = "1"></th>};
	             # 	foreach my $col (@matrixBook) {
	             # 		$print_header .= qq{<th colspan = "1">$m</th>};
	             # 	};
	             #	$print_header .= qq{</tr>};
}

#PRINT LATEX OUTPUT
# 	{\setlength{\arrayrulewidth}{0.05pt} %default is 0.4pt
#   \setlength{\arraycolsep}{2pt}%default is 5pt
#  \renewcommand{\arraystretch}{1.2}%default is 1

sub createout1 {
	my $L = $nRows - 1;
	foreach my $step ( 0 .. $nRows - 2 ) {
		$output[$step] .= qq|
			<p></p>
			<h4>Step $step</h4>
			<p>$boardnotes[$step]</p>
			<p>
		    <img src="http://uts.cc.utexas.edu/~rhart/cgi-bin/mathtex.cgi?
		    \\dpi{100}
		    \\def\\zN{$nRows}
		    \\def\\zL{$L}
		    \\fbox{\\xymatrix \@H= 5mm {$xymatrix[$step]}}
			" alt="" border=0 align=middle>
			</p>
			<p>$calcnotes[$step]</p>
			<p><img src="http://uts.cc.utexas.edu/~rhart/cgi-bin/mathtex.cgi?
			\\usepackage{euler}
			\\begin{equation*}
			\\begin{bmatrix}
				$a_tex[$step]
			\\end{bmatrix}
			\\end{equation*}
			" alt="" border=0 align=middle>
			<p>
			$formulanotes[$step] 
			<img src="http://uts.cc.utexas.edu/~rhart/cgi-bin/mathtex.cgi?
			\\usepackage{euler}
			\\begin{equation*}
			\\begin{bmatrix}
			$f_tex[$step]
			\\end{bmatrix}
			\\end{equation*}
			" alt="" border=0 align=middle></p>
		|;
	}
	return @output;
}

sub createout2 {
	my $L = $nRows - 1;
	foreach my $step ( $nRows - 1 .. 2 * $nRows - 2 ) {
		$output[$step] .= qq|
			<p>
			<h4>Step $step</h4>
			<p>
			<p>$boardnotes[$step]</p>
			<p>
		    <img src="http://uts.cc.utexas.edu/~rhart/cgi-bin/mathtex.cgi?
		    \\dpi{100}
		    \\def\\zN{$nRows}
		    \\def\\zL{$L}
		    \\fbox{\\xymatrix \@H= 5mm {$xymatrix[$step]}}
			" alt="" border=0 align=middle>
			</p><p>
			<img src="http://uts.cc.utexas.edu/~rhart/cgi-bin/mathtex.cgi?
			\\usepackage{euler}
			\\begin{equation*}
				$result[$step] 
			\\end{equation*}
			" alt="" border=0 align=middle>
			<p>
			<img src="http://uts.cc.utexas.edu/~rhart/cgi-bin/mathtex.cgi?
			\\usepackage{euler}
			\\begin{equation*}
				$formula[$step]
			\\end{equation*}
			" alt="" border=0 align=middle>
		|;
	}
	return @output;
}

sub createout3 {
	my $laststep = 2 * $nRows - 1;
	$output[$laststep] .= qq{
		<p>
		<h4>Step $laststep</h4>
		<p>
		$boardnotes[$step]
		<img src="http://uts.cc.utexas.edu/~rhart/cgi-bin/mathtex.cgi?
		\\usepackage{euler}
		\\begin{equation*}
			$result[$laststep]
		\\end{equation*}
		" alt="" border=0 align=middle>
		 <p>
		<img src="http://uts.cc.utexas.edu/~rhart/cgi-bin/mathtex.cgi?
		\\usepackage{euler}
		\\begin{equation*}
			$formula[$laststep]
		\\end{equation*}
		" alt="" border=0 align=middle>
		<p>
	};
	return @output;
}

#CGI SUBROUTINES
my $which_one = param('button_name');
my $stepmessage;
my $stepoutput = "";
my $nextstep;

sub choose_options {
	if ( $which_one == "Next step" ) {
		$stepUser     = $query->param('step');
		$nextstep = $stepUser;
		$nextstep++;
		$stepmessage = "<p>My new step is $stepUser</p>";
	}
	else {
		$stepUser     = 0;
		$nextstep = $stepUser;
		$nextstep++;
	}
	if ( $query->param("u[1][1]") ) {
		$matrixNum = $query->param('old_m_num');    #= $query->param("N");
		$nRows     = $query->param('N');            #= $query->param("N");
		$error .= " <p>My old N is $nRows </p>";
		$nCols = $nRows + 1;
		foreach my $row ( 1 .. $nRows ) {
			foreach my $col ( 1 .. $nCols ) {
				if (   ( $col == $row + 1 )
					or ( $col == $row )
					or ( $col == 1 and $row == $nRows )
					or $col == $nCols )
				{
					my $input = $query->param("u[$row][$col]");
					$input =~ s/\s+//g;
					if ( $input =~ m/^\-?\d+(\/\d+)?$/ ) {
						$u[$row][$col] = $input;
					}
					else {
						$inputerror .=
qq{<p>"$input" is not valid input. Entries must be an integer or a proper fraction. };
						if ( $input =~ m/\-?\d+(\/\d+)?/ ) {
							$u[$row][$col] = $&;
						}
						else {
							$u[$row][$col] = 0;
						}
						$inputerror .=
						  qq{The entry has been set to $u[$row][$col].</p>};
					}
				}
				else {
					$u[$row][$col] = 0;
				}
				$matrixBook[$matrixNum][ $row - 1 ][ $col - 1 ] = "$u[$row][$col]";
			}
		}
		copy($matrixNum);
	}
	elsif ( $query->param('m_num') && ( $query->param('m_num') != $matrixNum ) ) {
		$matrixNum = $query->param('m_num');
		copy($matrixNum);
	}
	elsif ( 0 == 1 ) {    # ($query->param('N') && ($query->param('N') != $nRows)) {
		$nRows = $query->param('N');
		unless ( ( $nRows >= 1 ) and ( $nRows <= 5 ) ) { $nRows = 3 }
		$nCols = $nRows + 1;
		randomMatrixCalc();
	}
	if ( $query->param('usegcf') ) {
		$usegcf = $query->param('usegcf');
		unless ( $usegcf == 1 ) { $usegcf = 0 }
	}
}

#PRINT HTML PAGE

print $query->header, $query->start_html('Chinese linear algebra'),
  h2('Determinants'), p, start_form, hr, "Problem:",
  popup_menu( -name => 'm_num', -values => \@JZSSproblems, -default => "" ), p,
  submit( -name => 'Choose new problem' ), p, $error, end_form;
$query->end_html;
my @steps;

#PROCESS SUBROUTINES
if ( defined( $query->param('m_num') ) ) {
	choose_options();
	$table_a      = a2table();
	$table_header = print_header();

	#&rowReduction;
	#&backSubstitution;
	#&divideANN;
	determinants();
	createout1();
	createout2();
	createout3();
	@steps = ( 0 .. 2 * $nRows - 2 );
	print start_form, hr, hidden( -name => 'N', -default => ["$nRows"] ),
	  hidden( -name => 'old_m_num', -default => ["$matrixNum"] ), p, $table_header,
	  $table_a, p, submit( -name => 'Recalculate with new values' ), p,
	  "$inputerror", p,

	  # reset(-name=>'Reset to original values'), p,
	  hr, qq{<p>$output[$stepUser]</p>}, p,
	  submit( -name => 'Next step', -value => 'Go to step' ),
	  popup_menu(
		-name     => 'step',
		-values   => \@steps,
		-default  => "$nextstep",
		-override => 1
	  ),

	  #qq{$newstep},
	  hr;

	# 		foreach my $i (1..3*$nRows) {
	# 			print qq{<p>Output $i</p>$output[$i]};
	# 		}
	# print qq{$stepoutput};
	end_form;
	$query->end_html;

	#$query->delete_all();
}

#
# 	my @names = $query->param;
# 	$error .="@names ";
#
# 	my $params = $query->Vars;
# 	print $params->{'address'};
# 	my @foo = split("\0",$params->{'foo'});
# 	my %params = $query->Vars;
# 	use CGI ':cgi-lib';
# 	$params = Vars;
# 	$error .="$params";
# 	foreach my $key (%params) {
# 		$error .= "<p>$key => $params{$key}</p>";
# 	}
# 	print qq{$error};

